﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="Task_When_ContinueWith.cs" company="JDML Consulting Ltd.">
//   Copyright 2011 Photon Project - http://photon.codeplex.com
// </copyright>
// <summary>
//   Defines the Task_When_ContinueWith type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Photon.Threading
{
    using System;
    using System.Threading;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using Mocks;
    using Testing;
    using Testing.Threading;

    [TestClass]
   public class Task_When_ContinueWith : AsynchronousTest
   {
      [TestMethod]
      [HostType("CHESS")]
      public void If_Adding_Continuations_On_Different_Threads()
      {
         var task = Task.Factory.From(() => MockDelegates.DoNothing);

         var done1 = false;
         var done2 = false;
         
         ThreadPool.QueueUserWorkItem(
            s => task.ContinueWith(() => done1 = true, TestTaskFactories.Synchronous));
         ThreadPool.QueueUserWorkItem(
            s => task.ContinueWith(() => done2 = true, TestTaskFactories.Synchronous));
         task.Start();
         
         AsyncUtility.SleepUntil(() => done1 && done2);
      }

      [TestMethod]
      public void If_Continuation_Task_Is_Null_Should_Throw_Argument_Null_Exception()
      {
         var task = Task.Factory.From(() => MockDelegates.DoNothing);
         
         var actualException = AssertException.Throws<ArgumentNullException>(
            () => task.ContinueWith((ITask)null, null));
         Assert.AreEqual("continuationTask", actualException.ParamName);
      }

      [TestMethod]
      public void Should_Return_Result_For_The_Continuation_In_Callback()
      {
         var task = TestTaskFactories.Synchronous.From(() => MockDelegates.DoNothing);
         task.ContinueWith(
            r1 => 1, 
            r2 => Assert.AreEqual(1, r2.Result), TestTaskFactories.Synchronous);
         task.Start();
      }

      [TestMethod, AsynchronousTest]
      [HostType("CHESS")]
      public void Should_Schedule_Dipatch_And_Return_Using_Supplied_Scheduler()
      {
         var dispatchedOnUIThread = TestStrings.Timeout;
         var returnedOnUIThread = TestStrings.Timeout;

         var task = Task.Factory.From(() => 1);
         
         // place on simulated UI queue.
         EnqueueAction(
            () => task.ContinueWith<int>(
               parentTask =>
               {
                  dispatchedOnUIThread = TestThreadInfo.FromCurrentThread().ThreadType == TestThreadType.TestThreadDispatcher
                                            ? TestStrings.Success
                                            : TestStrings.Failure;
               },
               r =>
               {
                  returnedOnUIThread = TestThreadInfo.FromCurrentThread().ThreadType == TestThreadType.TestThreadDispatcher
                                          ? TestStrings.Success
                                          : TestStrings.Failure;
               }, new TaskFactory(TaskScheduler.ForUISend())));

         task.Start(null);

         AsyncUtility.SleepUntil(() => dispatchedOnUIThread != TestStrings.Timeout && 
            returnedOnUIThread != TestStrings.Timeout);
         Assert.AreEqual(TestStrings.Success, dispatchedOnUIThread);
         Assert.AreEqual(TestStrings.Success, returnedOnUIThread);
         EnqueueCompleted();
      }
   }
}
